//! \file pairfile.hpp
//! \brief Purewell Library Pair File Header
//! \author Yubin Lim (purewell@gmail.com)
//! \since 2008-01-25

#ifndef __PWHDR_PAIRFILE_HPP__
#define __PWHDR_PAIRFILE_HPP__

#include "file.hpp"

namespace purewell
{

//! \brief Pair file interface.
class PWAPI PWPairFile : public PWFile
{
public:
	//! \brief Index.
	typedef enum _PAIR_T
	{
		PAIR_PRIMARY = 0,	//!< First FD index.
		PAIR_SECONDRY = 1,	//!< Second FD index.
		PAIR_FIRST = 0,		//!< First FD index.
		PAIR_SECOND = 1,	//!< Second FD index.
	} PAIR_T;

public:
	//! \brief Get second handle.
	//! \return Second file descriptor.
	inline int getHandle2(void) const
	{
		return m_fd2;
	}

	//! \brief Get handle.
	//! \param[in] idx Index. 0 or 1.
	//! \return File handle.
	inline int getHandle(size_t idx) const
	{
		return idx == 0 ? m_fd : m_fd2;
	}

public:
	//! \brief Attach file descriptors.
	//! \param[in] fd File descriptors.
	//! \return On success, true.
	virtual bool attach2(const int fd[2]);

	//! \brief Attach file descriptor.
	//! \param[in] fd File descriptor.
	//! \param[in] idx File descriptor index.
	//! \return On success, true.
	virtual bool attach(int fd, size_t idx);

	//! \brief Detach file descriptors.
	//! \param[out] fd File descriptors. If NULL, no operation.
	virtual void detach2(int* fd);

	//! \brief Detach file descriptor.
	//! \param[in] fd File descriptor.
	//! \param[in] idx File descriptor index.
	//! \return Old descriptor.
	int detach(int fd, size_t idx);

	virtual void destroy(void);

public:
	// File controls...

	//! \brief Set blocking mode.
	//! \param[in] block Blocking mode.
	//! \param[in] idx File descriptor index.
	//! \return On success, true.
	bool setModeBlock(bool block, size_t idx);

	//! \brief Get blocking mode.
	//! \param[out] block Blocking mode.
	//! \param[in] idx File descriptor index.
	//! \return On success, true.
	bool getModeBlock(bool& block, size_t idx) const;

	//! \brief Set asynchronous mode.
	//! \param[in] async Asynchronous mode.
	//! \param[in] idx File descriptor index.
	//! \return On success, true.
	bool setModeAsync(bool async, size_t idx);

	//! \brief Get asynchronous mode.
	//! \param[out] block Asynchronous mode.
	//! \param[in] idx File descriptor index.
	//! \return On success, true.
	bool getModeAsync(bool& block, size_t idx) const;

	//! \brief Set mode close on exec.
	//! \param[in] coe Close on exec mode.
	//! \param[in] idx File descriptor index.
	//! \return On success, true.
	bool setModeCloseOnExec(bool coe, size_t idx);

	//! \brief Get mode close on exec.
	//! \param[out] coe Close on exec mode.
	//! \param[in] idx File descriptor index.
	//! \return On success, true.
	bool getModeCloseOnExec(bool& coe, size_t idx) const;

	//! \brief Set mode.
	//! \param[in] mode Mode flags.
	//! \param[in] idx File descriptor index.
	//! \return On success, true.
	bool setMode(int mode, size_t idx);

	//! \brief Get mode.
	//! \param[out] mode Mode flags.
	//! \param[in] idx File descriptor index.
	//! \return On success, true.
	bool getMode(int& mode, size_t idx) const;

	//! \brief Duplicate file descriptor.
	//! \param[in] srcfd Source file descriptor.
	//! \param[in] idx File descriptor index.
	//! \return On success, true.
	//! \warning Without destroy method, initialized file descriptor will be leaked.
	bool duplicate(int srcfd, size_t idx);

	//! \brief Duplicate file descriptor.
	//! \param[in] srcfd Source file descriptor.
	//! \param[in] newfd New file descriptor to allocate.
	//! \param[in] idx File descriptor index.
	//! \return On success, true.
	//! \warning Without destroy method, initialized file descriptor will be leaked.
	bool duplicate(int srcfd, int newfd, size_t idx);


public:
	//! \brief Read data from file descriptor.
	//! \param[out] buf Buffer.
	//! \param[in] blen Buffer length.
	//! \param[in] idx File descriptor index.
	//! \return On success, read data size.
	virtual ssize_t read(void* buf, size_t blen, size_t idx);

	//! \brief Write data to file descriptor.
	//! \param[in] buf Buffer.
	//! \param[in] blen Buffer length.
	//! \param[in] idx File descriptor index.
	//! \return On success, written data size.
	virtual ssize_t write(const void* buf, size_t blen, size_t idx);

	//! \brief Read data from file descriptor parallely.
	//! \param[out] buf Buffer.
	//! \param[in] blen Buffer length.
	//! \param[in] offset Offset to read.
	//! \param[in] idx File descriptor index.
	//! \return On success, read size. In case of error, it returns -1.
	virtual ssize_t readParallel(void* buf, size_t blen, off_t offset,
		size_t idx);

	//! \brief Write data to file descriptor parallely.
	//! \param[in] buf Buffer.
	//! \param[in] blen Buffer length.
	//! \param[in] offset Offset to write.
	//! \param[in] idx File descriptor index.
	//! \return On success, read size. In case of error, it returns -1.
	virtual ssize_t writeParallel(const void* buf, size_t blen,
		off_t offset, size_t idx);

public:
	explicit PWPairFile();
	virtual ~PWPairFile();

protected:
	virtual bool attach(int fd);
	virtual int detach(void);

protected:
	//! \brief Secondary file descriptor.
	int m_fd2;
};


};

#endif//!__PWHDR_PAIRFILE_HPP__

